﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Runtime.Serialization;
using KPIS.GERP.Models.Class;
using KPIS.GERP.Models.HRM;
using KPIS.GERP.Models.ICM;
using KPIS.GERP.Models.SYS.ViewModel;
using KPIS.DBM;
using System.Data;

namespace KPIS.GERP.Models.SYS
{
    [DataContract, Table("SysApprovalTask")]
    public class ApprovalTask
    {
        [DataMember, Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public virtual int ApprovalTaskId { get; set; }
        [DataMember] public virtual string Code { get; set; }
        [DataMember] public virtual int StepNo { get; set; }
        [DataMember] public virtual string OriginalRequestTitle { get; set; }
        [DataMember] public virtual decimal? RequestAmount { get; set; }
        [DataMember] public virtual string Reasons { get; set; }
        [DataMember] public virtual int ActionCount { get; set; }
        [DataMember, ForeignKey("CurrentApprovePath")] public virtual int? CurrentAppPathId { get; set; }
        [DataMember, ForeignKey("OriginalApplyToEmployee")] public virtual int OriginalApplyToEmpId { get; set; }
        [DataMember, ForeignKey("OriginalApproveProcess")] public virtual int OriginalAppPrcId { get; set; }
        [DataMember] public virtual ApproveProcess OriginalApproveProcess { get; set; }
        [DataMember] public virtual ApprovalTaskStatus ApprovalTaskStatus { get; set; }
        [DataMember] public virtual Employee OriginalApplyToEmployee { get; set; }
        [DataMember] public virtual ApprovePath CurrentApprovePath { get; set; }
        [DataMember] public virtual ICollection<ApprovalTaskDtl> ApprovalTaskDtls { get; set; }
        [DataMember] public virtual string RecordStatus { get; set; }
        [DataMember] public virtual int? CreatedBy { get; set; }
        [DataMember] public virtual DateTime? CreatedWhen { get; set; }
        [DataMember] public virtual int? UpdatedBy { get; set; }
        [DataMember] public virtual DateTime? UpdatedWhen { get; set; }
        [DataMember] public virtual int? RefId { get; set; }
        [DataMember] public virtual string ConfirmAs { get; set; }
        [DataMember] public virtual string ApproveAs { get; set; }
        [DataMember] public virtual bool  Completed { get; set; }
        [DataMember] public virtual int? CompletedActionBy { get; set; }
        [DataMember] public virtual DateTime?  ApprovedDate { get; set; } // เพิ่ม
        [DataMember] public virtual int? ApprovedBy { get; set; } // เพิ่ม
        [DataMember] public virtual DateTime? CompletedActionWhen { get; set; }
        [DataMember] public virtual int? CompletedDtlId { get; set; }
        [DataMember] public virtual int? CompletedMessageId { get; set; }
        [DataMember] public virtual string CompletedCommandAction { get; set; }
        [DataMember,NotMapped] public virtual ApprovalTaskDtl CompletedDtl { get; set; }
        [DataMember,NotMapped] public virtual Message CompletedMessage { get; set; }

        public virtual void Command(CommandAction action, bool foundSomeApprover, string reasons, int? byEmpId = null)
        {
            switch (action)
            {
                case CommandAction.Initial:
                    if(foundSomeApprover)
                    {
                        ApprovalTaskStatus = ApprovalTaskStatus.WaitCommanderApprove;
                    }
                    else
                    {
                        ApprovalTaskStatus = ApprovalTaskStatus.Freeze;
                        Reasons = reasons + ", Not found some approver";
                    }
                    break;
                case CommandAction.Approve:
                    ApprovedBy = byEmpId;
                    ApprovedDate = DateTime.Now;
                    ApprovalTaskStatus = ApprovalTaskStatus.Locked;
                    break;
                case CommandAction.Forward: 
                    ApprovalTaskStatus = ApprovalTaskStatus.WaitCommanderApprove;
                    break;
                case CommandAction.Reject: 
                    ApprovalTaskStatus = ApprovalTaskStatus.Locked;
                    break;
                case CommandAction.Pending : 
                    ApprovalTaskStatus = ApprovalTaskStatus.WaitCommanderApprove;
                    break;
                case CommandAction.Information : 

                    break;
                case CommandAction.SendBack : 
                    ApprovalTaskStatus = ApprovalTaskStatus.WaitCommanderApprove;
                    break;
                case CommandAction.Lock : 
                    ApprovalTaskStatus = ApprovalTaskStatus.Locked;
                    break;
                case CommandAction.Cancel : 
                    ApprovalTaskStatus = ApprovalTaskStatus.Locked;
                    break;

            }
            ActionCount++;
            Reasons = reasons;
            UpdatedBy = byEmpId;
            UpdatedWhen = DateTime.Now;
        }

        public virtual void CreateNewTask(string title, int applyToEmpId, int appPrcId, int createByEmpId, int refId, string confirmAs, string approveAs, string refNo, decimal? amount = null)
        {
            OriginalRequestTitle = title;
            Code = refNo; //CodeGenerate.GetNextCode(CodeGenerate.TransectionType.ApprovalTask);
            OriginalApplyToEmpId = applyToEmpId;
            OriginalAppPrcId = appPrcId;
            RequestAmount = amount;
            CreatedBy = createByEmpId;
            ActionCount++;
            CreatedWhen = DateTime.Now;
            RecordStatus = SYS.RecordStatus.UsedStatus;
            ApprovalTaskStatus = ApprovalTaskStatus.Initial;
            RefId = refId;
            ConfirmAs = confirmAs;
            ApproveAs = approveAs;
        }

        public void OnWorkflowStart(CreateApprovalTaskVM model)
        {
            using(GERPContext db = new GERPContext(true))
            {
                var originalApproveProcess = db.ApproveProcesses.Find(this.OriginalAppPrcId); 
                if(originalApproveProcess.AppPrcGrpId == 1) // ขอลา ทั้งกลุ่ม Process ใช้วิธีนี้หมด
                {
                    db.PsAbsences.FirstOrDefault(o => o.AbsenceId == RefId).RecordStatus = ConfirmAs;
                } else if(originalApproveProcess.AppPrcGrpId == 6) // คำขออนุมัติแจ้งความประสงค์
                {
                    db.PrePurchaseRequests.FirstOrDefault(o => o.PprId == RefId).RecordStatus = ConfirmAs;
                } else if(originalApproveProcess.AppPrcGrpId == 7) // ขอเบิก
                {
                    db.RequestParcels.FirstOrDefault(o => o.ReqParcelId == RefId).RecordStatus = ConfirmAs;
                }else if(originalApproveProcess.AppPrcGrpId == 8 // ขออนุมัติขอซื้อขอจ้างเกิน๑๐๐๐๐๐บาท
                    || originalApproveProcess.AppPrcGrpId == 9) // ขออนุมัติขอซื้อขอจ้างไม่เกิน๑๐๐๐๐๐บาท
                {
                    db.PurchaseRequests.FirstOrDefault(o => o.PrId == RefId).RecordStatus = ConfirmAs;
                }else if(originalApproveProcess.AppPrcGrpId == 10 // ขออนุมัติใบสั่งเกิน๑๐๐๐๐๐บาท
                    || originalApproveProcess.AppPrcGrpId == 11 // ขออนุมัติใบสั่งไม่เกิน๑๐๐๐๐๐บาท
                    || originalApproveProcess.AppPrcGrpId == 13) // ขออนุมัติงานสัญญา
                {
                    db.PurchaseOrders.FirstOrDefault(o => o.PoId == RefId).RecordStatus = ConfirmAs;
                }else if(originalApproveProcess.AppPrcGrpId == 12) // ขออนุมัติประกาศ
                {
                    db.Bids.FirstOrDefault(o => o.BidId == RefId).RecordStatus = ConfirmAs;
                }
                else if (originalApproveProcess.AppPrcGrpId == 14) // ตรวจรับ
                {
                    db.DeliveryNotes.FirstOrDefault(o => o.DnId == RefId).RecordStatus = ConfirmAs;
                }
                else if (originalApproveProcess.AppPrcGrpId == 15) // คำสั่ง
                {
                    db.PsCommands.FirstOrDefault(o => o.CmdId == RefId).RecordStatus = ConfirmAs;
                }
                db.SaveChanges();
            }
        }

        public void OnWorkflowEscalateStep (CommandActionVM model)
        {
            if(StepNo == 1)
            {
                 
            }
        }

        public void OnWorkflowComplete (CommandActionVM model)
        {
            string updateReferenceTableRecordStatus = null;
            switch (model.CommandAction)
            {
                case CommandAction.Approve:
                    updateReferenceTableRecordStatus = ApproveAs;
                    break; 
                case CommandAction.Cancel:
                    updateReferenceTableRecordStatus = SYS.RecordStatus.WaitStatus;
                    break;
                case CommandAction.Reject:
                    updateReferenceTableRecordStatus = SYS.RecordStatus.RejectStatus;
                    break;
                case CommandAction.TakeBack:  // คนที่ส่งมาในขั้นตอนที่แล้ว ดึงกลับขั้นตอน (ก่อนผู้อนุมัติขั้นตอนปัจจุบันจะทำคำสั่งไปเป็น Step ต่อไป) #รอ Implement ยังไม่แน่ใจว่าจะทำได้ยังไง
                case CommandAction.SendBack:  // ส่งย้อนกลับไปยังขั้นตอนใดๆ ก็ได้ที่อยู่ก่อนหน้า #รอ Implement ยังไม่แน่ใจว่าจะทำได้ยังไง 
                case CommandAction.Forward:// Forward จริงๆ อันนี้ไม่น่าจะมีในตอนEvent Complete 
                case CommandAction.Pending:// Pending ผู้บังคับบัญชาสั่งพักคำขอไว้ #ต้องทำอะไรบ้าง ยังไม่แน่ใจ
                case CommandAction.Information://กรณี R/Read-Only / แจ้งให้ทราบอย่างเดียว ไม่มี Action (ยังไม่แน่ใจว่าจะมาตรง Complete ได้อย่างไร)
                case CommandAction.Lock: // Lock By System อาจเกิด Error เลยทำให้โปรแกรมสั่ง Command Lock (ต้องไปเช็คดูอีกที)
                    updateReferenceTableRecordStatus = null;
                    break;
            }

            
            using(GERPContext db = new GERPContext(true))
            {
                var message = db.Messages.Find(model.MessageId);
                message.Remarks = model.Remarks + ", " + message.Remarks;
                string strSQL = "";
                if(this.OriginalApproveProcess.AppPrcGrpId == 1) // ขอลา ทั้งกลุ่ม Process ใช้วิธีนี้หมด
                {
                   if(!string.IsNullOrWhiteSpace(updateReferenceTableRecordStatus))
                   {
                       db.PsAbsences.FirstOrDefault(o => o.AbsenceId == RefId).RecordStatus = updateReferenceTableRecordStatus;
                   }

                } else if(this.OriginalApproveProcess.AppPrcGrpId == 6) // คำขออนุมัติแจ้งความประสงค์
                {
                   if(!string.IsNullOrWhiteSpace(updateReferenceTableRecordStatus))
                   {
                       var prePurchareRequest = db.PrePurchaseRequests.FirstOrDefault(o => o.PprId == RefId);
                       prePurchareRequest.RecordStatus = updateReferenceTableRecordStatus;
                       prePurchareRequest.Reason = model.Remarks + " - " + prePurchareRequest.Reason;
                   }
                } else if(this.OriginalApproveProcess.AppPrcGrpId == 7) // ขอเบิก
                {
                   if(!string.IsNullOrWhiteSpace(updateReferenceTableRecordStatus)) db.RequestParcels.FirstOrDefault(o => o.ReqParcelId == RefId).RecordStatus = updateReferenceTableRecordStatus;
                }else if(this.OriginalApproveProcess.AppPrcGrpId == 8 // ขออนุมัติขอซื้อขอจ้างเกิน๑๐๐๐๐๐บาท
                    || this.OriginalApproveProcess.AppPrcGrpId == 9) // ขออนุมัติขอซื้อขอจ้างไม่เกิน๑๐๐๐๐๐บาท
                {
                   if(!string.IsNullOrWhiteSpace(updateReferenceTableRecordStatus)) db.PurchaseRequests.FirstOrDefault(o => o.PrId == RefId).RecordStatus = updateReferenceTableRecordStatus;
                }else if(this.OriginalApproveProcess.AppPrcGrpId == 10 // ขออนุมัติใบสั่งเกิน๑๐๐๐๐๐บาท
                    || this.OriginalApproveProcess.AppPrcGrpId == 11 // ขออนุมัติใบสั่งไม่เกิน๑๐๐๐๐๐บาท
                    || this.OriginalApproveProcess.AppPrcGrpId == 13) // ขออนุมัติงานสัญญา
                {
                   if(!string.IsNullOrWhiteSpace(updateReferenceTableRecordStatus)) db.PurchaseOrders.FirstOrDefault(o => o.PoId == RefId).RecordStatus = updateReferenceTableRecordStatus;
                }
                else if (this.OriginalApproveProcess.AppPrcGrpId == 14) // ขออนุมัติตรวจรับ
                {
                    #region DeliveryNote
                    DeliveryNote model14 = db.DeliveryNotes.Include("PurchaseOrder.Bidder").FirstOrDefault(o => o.DnId == RefId);
                    List<DeliveryNoteItem> modelItems14 = db.DeliveryNoteItems.Include("PoInstallItem.BidderQuotation.PurchaseRequestItem")
                        .Where(o => o.DnId == RefId).ToList();

                    model14.RecordStatus = updateReferenceTableRecordStatus;

                    foreach (var modelItem14 in modelItems14)
                    {
                        List<PrePurchaseRequestItem> modelPreItems = db.PrePurchaseRequestItems
                            .Include("ProjectOperationExpense.ProjectExpense.MasBudgetExpense")
                            .Include("ProjectOperationExpense.ProjectOperation")
                            .Where(m => m.PrItemId == modelItem14.PoInstallItem.BidderQuotation.PurchaseRequestItem.PrItemId).ToList();

                        strSQL = "insert into fim_money_requests"
                                + " (bgm_source_seq, bgm_year, work_area_seq"
                                + ", bgm_exp_grp_seq, event_seq, money_req_date, use_advance"
                                + ", advance_bgm_source_seq, ref_no, money_req_name"
                                + ", bgm_proj_oper_seq, emp_seq, job_site_seq"
                                + ", contact_seq, icm_dn_seq, allow"
                                + ", record_status, created_by, created_when)"
                                + " values"
                                + " (@bgm_source_seq, @bgm_year, @work_area_seq"
                                + ", @bgm_exp_grp_seq, @event_seq, @money_req_date, @use_advance"
                                + ", @advance_bgm_source_seq, @ref_no, @money_req_name"
                                + ", @bgm_proj_oper_seq, @emp_seq, @job_site_seq"
                                + ", @contact_seq, @icm_dn_seq, @allow"
                                + ", @record_status, @created_by, @created_when);"
                                + " select scope_identity();";

                        strSQL = strSQL.Replace("@bgm_source_seq", modelPreItems[0].ProjectOperationExpense.ProjectExpense.BgSourceId.ToString().Length > 0 ? modelPreItems[0].ProjectOperationExpense.ProjectExpense.BgSourceId.ToString() : "null")
                            .Replace("@bgm_year", modelPreItems[0].ProjectOperationExpense.ProjectOperation.BgYear.ToString().Length > 0 ? modelPreItems[0].ProjectOperationExpense.ProjectOperation.BgYear.ToString() : "null")
                            .Replace("@work_area_seq", "1")
                            .Replace("@bgm_exp_grp_seq", modelPreItems[0].ProjectOperationExpense.ProjectExpense.MasBudgetExpense.BgExpGrpId.ToString().Length > 0 ? modelPreItems[0].ProjectOperationExpense.ProjectExpense.MasBudgetExpense.BgExpGrpId.ToString() : "null")
                            .Replace("@event_seq", "11")
                            .Replace("@money_req_date", "'" + (DateTime.Today.Year) + "/" + DateTime.Today.Month + "/" + DateTime.Today.Day + "'")
                            .Replace("@use_advance", "'0'")
                            .Replace("@advance_bgm_source_seq", "null")
                            .Replace("@ref_no", "''")
                            .Replace("@money_req_name", "'รายการเบิกเงินจากการตรวจรับเลขที่ " + model14.Code + "'")
                            .Replace("@bgm_proj_oper_seq", modelPreItems[0].ProjectOperationExpense.ProjOperId.ToString().Length > 0 ? modelPreItems[0].ProjectOperationExpense.ProjOperId.ToString() : "null")
                            .Replace("@emp_seq", model14.DeliveryEmpId.ToString().Length > 0 ? model14.DeliveryEmpId.ToString() : model14.CreatedBy.ToString())
                            .Replace("@job_site_seq", model14.DeliveryJobSiteId.ToString().Length > 0 ? model14.DeliveryJobSiteId.ToString() : "null")
                            .Replace("@contact_seq", model14.PurchaseOrder.Bidder.ConId.ToString().Length > 0 ? model14.PurchaseOrder.Bidder.ConId.ToString() : "null")
                            .Replace("@icm_dn_seq", model14.DnId.ToString().Length > 0 ? model14.DnId.ToString() : "null")
                            .Replace("@allow", "'1'")
                            .Replace("@record_status", "'W'")
                            .Replace("@created_by", model14.DeliveryEmpId.ToString().Length > 0 ? model14.DeliveryEmpId.ToString() : "null")
                            .Replace("@created_when", "'" + (DateTime.Today.Year) + "/" + DateTime.Today.Month + "/" + DateTime.Today.Day + "'");

                        DBManager dbManager = new DBManager(DataProvider.SqlServer, System.Configuration.ConfigurationManager.ConnectionStrings["GERPContext"].ConnectionString);
                        dbManager.Open();
                        int nMoneyReqSeq = Convert.ToInt32(dbManager.ExecuteDataTable(CommandType.Text, strSQL).Rows[0][0]);
                        //var nMoneyReqSeq = db.Database.ExecuteSqlCommand(strSQL);
                        dbManager.Close();

                        foreach (var modelPreItem in modelPreItems)
                        {
                            strSQL = "insert into fim_money_request_dtls"
                                + " (money_req_seq, money_req_dtls_name, bgm_proj_oper_exp_seq"
                                + ", job_site_seq, percent_vat, percent_tax, amount"
                                + ", amount_vat, amount_tax"
                                + ", record_status, created_by, created_when)"
                                + " values"
                                + " (@money_req_seq, @money_req_dtls_name, @bgm_proj_oper_exp_seq"
                                + ", @job_site_seq, @percent_vat, @percent_tax, @amount"
                                + ", @amount_vat, @amount_tax"
                                + ", @record_status, @created_by, @created_when)";

                            strSQL = strSQL.Replace("@money_req_seq", nMoneyReqSeq.ToString())
                                .Replace("@money_req_dtls_name", "'" + modelItem14.MasResourceItem.Name + "'")
                                .Replace("@bgm_proj_oper_exp_seq", modelPreItem.ProjectOperationExpense.ProjOperExpId.ToString().Length > 0 ? modelPreItem.ProjectOperationExpense.ProjOperExpId.ToString() : "null")
                                .Replace("@job_site_seq", model14.DeliveryJobSiteId.ToString().Length > 0 ? model14.DeliveryJobSiteId.ToString() : "null")
                                .Replace("@percent_vat", "null")
                                .Replace("@percent_tax", "null")
                                .Replace("@amount_vat", modelItem14.VatAmount.ToString().Length > 0 ? modelItem14.VatAmount.ToString() : "null")
                                .Replace("@amount_tax", "null")
                                .Replace("@amount", modelItem14.NetAmount.ToString().Length > 0 ? modelItem14.NetAmount.ToString() : "null")
                                .Replace("@record_status", "'W'")
                                .Replace("@created_by", model14.DeliveryEmpId.ToString().Length > 0 ? model14.DeliveryEmpId.ToString() : "null")
                                .Replace("@created_when", "getdate()");

                            db.Database.ExecuteSqlCommand(strSQL);
                        }
                    }
                    #endregion
                }
                else if (this.OriginalApproveProcess.AppPrcGrpId == 12) // ขออนุมัติประกาศ
                {
                    if(!string.IsNullOrWhiteSpace(updateReferenceTableRecordStatus))
                        db.Bids.FirstOrDefault(o => o.BidId == RefId).RecordStatus = updateReferenceTableRecordStatus;
                }
                else if (this.OriginalApproveProcess.AppPrcGrpId == 15) // ขออนุมัติคำสั่ง
                {
                    if(!string.IsNullOrWhiteSpace(updateReferenceTableRecordStatus))
                    {
                        var command = db.PsCommands.FirstOrDefault(o => o.CmdId == RefId);
                        command.RecordStatus = updateReferenceTableRecordStatus;
                        command.CmdStatus = "A";
                        if(model.CommandAction == CommandAction.Approve)
                        {
                            command.ApproverId = model.ByEmpId;
                            command.ApprovedPositions = Convert.ToString(db.Employees.Find(model.ByEmpId).PosId);
                            command.ApprovedName = db.Employees.Find(model.ByEmpId).FullName;
                            command.ApprovedDate = DateTime.Now;
                        }
                    }
                }

                ApprovalTask thisApprovalTask = db.ApprovalTasks.Find(ApprovalTaskId);
                thisApprovalTask.Completed = true;
                thisApprovalTask.CompletedActionBy = model.ByEmpId;
                thisApprovalTask.CompletedDtlId = model.Message.ApprovalTaskDtlId;
                thisApprovalTask.CompletedMessageId = model.MessageId;
                thisApprovalTask.CompletedCommandAction = model.CommandAction.ToString();
                db.SaveChanges();
            }
        }
        
        public void OnWorkflowFailed (CommandActionVM model, string errorReasons)
        {
            Reasons = errorReasons;
            ApprovalTaskStatus = ApprovalTaskStatus.Locked;
            ActionCount++;
            UpdatedBy = model.ByEmpId;
            UpdatedWhen = DateTime.Now;
        }


    }
}